#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>


void copy_file(const char* srcpath, const char* destpath);
void copy_dir(const char* srcpath, const char* destpath);

int main(int argc, char** argv)
{
    if (argc == 3)
    {
        copy_dir(argv[1], argv[2]);
    }
    else
    {
        printf("请按照以下格式进行输入：\n");
        printf("例：\na.out 123 456(其中123为源目录，456为目标目录)");
    }
    return 0;
}

/**
    copy_file:拷贝文件
    @srcpath:源文件路径
    @destpath:目标文件路径
 */
void copy_file(const char* srcpath, const char* destpath)
{
    printf("copy file:%s==>%s\n", srcpath, destpath);
    //1.打开源文件
    int fd_src = open(srcpath, O_RDONLY);
    if (fd_src == -1)
    {
        perror("open src error");
        exit(1);
    }

    //2.打开目标文件
    int fd_dest = open(destpath, O_WRONLY | O_CREAT, 0777);
    if (fd_dest == -1)
    {
        perror("open dest error");
        exit(1);
    }

    //3.不断的读取源文件内容并写入到目标文件中
    char buf[100] = { 0 };
    while (1)
    {
        memset(buf, 0, sizeof(buf));

        int ret = read(fd_src, buf, sizeof(buf));
        if (ret <= 0)
            break;//读完了/出错了
        write(fd_dest, buf, ret);
    }
    close(fd_dest);
    close(fd_src);
}
/**
    copy_dir:拷贝目录
    @srcpath:源目录
    @destpath:目标目录
 */

void copy_dir(const char* srcpath, const char* destpath)
{
    //1.创建目标目录
    mkdir(destpath, 0777);

    //2.打开源目录
    DIR* dir = opendir(srcpath);
    if (dir == NULL)
    {
        printf("srcpath = %s\n", srcpath);
        perror("opendir error");
        exit((1));
    }

    struct dirent* dirp = NULL;
    char srcfilename[500] = { 0 };
    char destfilename[500] = { 0 };

    //3.读取目录相
    while (dirp = readdir(dir))//将readdir的返回值赋值给dirp，并判断真假
    {
        //合成绝对路径
        memset(srcfilename, 0, sizeof(srcfilename));
        memset(destfilename, 0, sizeof(destfilename));
        sprintf(srcfilename, "%s/%s", srcpath, dirp->d_name);
        sprintf(destfilename, "%s/%s", destpath, dirp->d_name);

        //获取文件属性
        struct stat st;
        stat(srcfilename, &st);
        if (S_ISREG(st.st_mode))//如果是文件
        {
            copy_file(srcfilename, destfilename);
        }
        else if (S_ISDIR(st.st_mode))//如果是目录
        {
            if (strcmp(dirp->d_name, ".") != 0 && strcmp(dirp->d_name, "..") != 0)
            {
                copy_dir(srcfilename, destfilename);
            }
        }
    }
    closedir(dir);
}